#ifndef ANE_JSON_PARSER
#define ANE_JSON_PARSER

#ifdef ANEJSON_EXPORTS
#define ANEJSON_API __declspec(dllexport)
#else
#define ANEJSON_API __declspec(dllimport)
#endif



typedef void * JSONObject;

//////////////////////////////////////////////////////////////////////////
// class CJSONParser
//////////////////////////////////////////////////////////////////////////
class ANEJSON_API CJSONParser {
public:
	CJSONParser(void);
	~CJSONParser(void);

private:
	JSONObject m_json_ctx;

public:
	// Call this method to parse the JSON string before you call the Get methods
	JSONObject ParseJSON(char *json_string);

	JSONObject haveObj(JSONObject obj, const char *name);
	int getType(JSONObject obj);
	bool getBoolean(JSONObject obj);
	int getInt(JSONObject obj);
	double getDouble(JSONObject obj);
	const char *getString(JSONObject obj);
	// Get methods
	JSONObject ObjectGetObject(JSONObject obj, char *name);
	bool ObjectGetBoolean(JSONObject obj, char *name);
	int ObjectGetInt(JSONObject obj, char *name);
	double ObjectGetDouble(JSONObject obj, char *name);
	const char *ObjectGetString(JSONObject obj, char *name);
	JSONObject ObjectGetArrayObject(JSONObject obj, char *name);
	int ArrayLength(JSONObject arr);
	JSONObject ArrayGetObject(JSONObject arr, int idx);
	bool ArrayGetBoolean(JSONObject arr, int idx);
	int ArrayGetInt(JSONObject arr, int idx);
	double ArrayGetDouble(JSONObject arr, int idx);
	const char *ArrayGetString(JSONObject arr, int idx);
	JSONObject ArrayGetArray(JSONObject arr, int idx);

};



//////////////////////////////////////////////////////////////////////////
// class CJSONFormer
//////////////////////////////////////////////////////////////////////////
class ANEJSON_API CJSONFormer{
public:
	CJSONFormer(void);
	~CJSONFormer(void);

private:
	JSONObject m_json_ctx;
	int			m_ref_count;

public:
	// Call this method to get the root object
	JSONObject GetRootObject(void);
	void ReleaseRootObject(void);

	static void DestroyJSONObject(JSONObject jobj);

	// Add methods
	JSONObject ObjectAddObject(JSONObject obj, char *name);
	bool ObjectAddBoolean(JSONObject obj, char *name, bool val);
	bool ObjectAddInt(JSONObject obj, char *name, int val);
	bool ObjectAddDouble(JSONObject obj, char *name, double val);
	bool ObjectAddString(JSONObject obj, char *name, const char *val);
	JSONObject ObjectAddArray(JSONObject obj, char *name);
	bool ArrayPushBoolean(JSONObject arr, bool val);
	bool ArrayPushInt(JSONObject arr, int val);
	bool ArrayPushDouble(JSONObject arr, double val);
	bool ArrayPushString(JSONObject arr, const char *val);
	JSONObject ArrayPushObject(JSONObject arr);

	// Generate the JSON string from the JSON object
	const char *GenJSONString(JSONObject obj);
	const char *GenJSONString(void);
};

typedef enum 
{
	ANE_json_type_null,
	ANE_json_type_boolean,
	ANE_json_type_double,
	ANE_json_type_int,
	ANE_json_type_object,
	ANE_json_type_array,
	ANE_json_type_string
}ANE_json_type;

typedef struct _AneVal
{
	ANE_json_type type;
	const char *name;
	union
	{
		unsigned char _boolean;
		JSONObject _object;
		JSONObject _array;
		int			_number_int;
		double		_number_double;
		const char * _string;
	}val;
}AneVal;

typedef void (*JSONFind_CallBack)(AneVal *val, void *userdata);
ANEJSON_API void ANEJSON_SetUserData(void *userdata);
ANEJSON_API void ANEJSON_SearchObject(JSONObject jsobj, JSONFind_CallBack findcb, void *userdata);

ANEJSON_API void ANEJSON_SearchArray(JSONObject jsarray, JSONFind_CallBack findcb, void *userdata);
ANEJSON_API int ANEJSON_GetArray(JSONObject jsarray);


ANEJSON_API int AneSendEvent(const char *eventName, CJSONFormer *jfParam);
ANEJSON_API int AneSendEventstr(const char *eventName, const char *jsonstr);

#define RETURN_JSON_STRING(json_former) json_former.ReleaseRootObject(); return (char*)json_former.GetRootObject();
#define ENTERFUNCTION(fname);	CJSONParser jp; \
	CJSONFormer jf; \
	JSONObject jobj; \


#define CHECKPARAMETER();		jobj = jp.ParseJSON(params); if (NULL == jobj) { return NULL; }
#define LEAVEFUNCTION(fname);	 RETURN_JSON_STRING(jf);
#endif // ANE_JSON_PARSER
